/**
 *  @file DLinkedList.h
 */
 
#ifndef __DLINKEDLIST_H_
#define __DLINKEDLIST_H_

#ifdef __cplusplus
extern "C" {
#endif

/**
 *  a doubly-linked list structure; to be embedded in other structures
 */
typedef struct _dllist {
    struct _dllist * pPrev;
    struct _dllist * pNext;
} dllist_t;

/**
 *  A macro to retrieve the pointer to the original structure in which the
 *  above doubly-linked list structure is embedded.
 *  The idea is just to subtract the offset of the doubly-linked list within
 *  the original structure from the address of the doubly-linked list.
 *
 *  ORGTYPE -- data type of the original structure
 *  field -- name of doubly-linked list field within the original structure
 *  pList -- address of the doubly-linked list
 */

#define GETORGPTR(ORGTYPE, field, pList) \
     (ORGTYPE*)DL_GetOrgPtr((void*)pList, (void*)(&(((ORGTYPE*)0)->field)))

/**
 *  Functions to manipulate some common operations
 *  of a doubly linked list: adding, retrieving and deleting a entry.
 */
void DL_InitDlList(dllist_t *pList);
void DL_AddEntryToHead(dllist_t *pList, dllist_t ** pHead, dllist_t ** pTail);
void DL_AddEntryToTail(dllist_t *pList, dllist_t ** pHead, dllist_t ** pTail);
void DL_InsertEntry(dllist_t *pList, dllist_t * pPrevEntry, dllist_t * pNextEntry);
dllist_t * DL_GetNextEntry(dllist_t *pList);
dllist_t * DL_GetPrevEntry(dllist_t *pList);	
dllist_t * DL_DeleteEntry(dllist_t *pList, dllist_t ** pHead, dllist_t ** pTail);
void DL_BreakupLink(dllist_t *pList);
void * DL_GetOrgPtr(void *pList, void *pOffset);

#ifdef __cplusplus
}
#endif

#endif
